﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Xml;

namespace VideoFlowTagger
{
	/// <summary>
	/// The main entry point to use this library. 
	/// </summary>
    public class VideoFile
    {
		private String filename = "";
		private iTunesMetadata metadata = new iTunesMetadata();
		public String exePath = "";
		private String picPath = "";

        public VideoFile(String filename)
        {
            this.filename = filename;
			this.exePath = ResolveEXEPath();
        }
		
		public VideoFile(String filename, iTunesMetadata metadata)
		{
			this.filename = filename;
			this.metadata = metadata;
			this.exePath = ResolveEXEPath();
		}
		
		public iTunesMetadata GetiTunesMetadata() 
		{
			return this.metadata;
		}
		
		public void Start()
		{
			String arguments = "\"" + filename + "\" " + metadata.ToString();
			
			// Specify process information
            ProcessStartInfo psi = new ProcessStartInfo(exePath, arguments);
            psi.WindowStyle = ProcessWindowStyle.Normal;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = true;
            psi.RedirectStandardOutput = true;
			psi.CreateNoWindow = true;
            
            // Start the process
            Process p = Process.Start(psi);
			p.Close();
		}

        public void Read()
        {
            String textFile = filename.Substring(0, filename.Length - 3) + "txt";

            GenerateTextFile();
            GeneratePicture();

            StreamReader reader = File.OpenText(textFile);

            while (!reader.EndOfStream)
            {
                String line = reader.ReadLine();
                int atomIndex = line.IndexOf("Atom ") + 6;
                int valueIndex = line.IndexOf("contains: ") + 10;

                if (atomIndex != -1)
                {
                    // 4 char value
                    String atomValue = line.Substring(atomIndex, 4);
                    String value = line.Substring(valueIndex, line.Length - valueIndex);

                    // Can either be Rating or Person
                    if (atomValue == "----")
                    {
                        String atomSignValue = line.Substring(atomIndex + 7, 25);

                        // determined it's a Rating
                        if (atomSignValue == "com.apple.iTunes;iTunEXTC")
                        {
                            atomValue = "extc";
                            value = "\"" + value + "\" name=iTunEXTC domain=com.apple.iTunes";

                            metadata.SetValue(atomValue, value);
                        }
                        else if (atomSignValue == "com.apple.iTunes;iTunMOVI")
                        {
                            // Remove the artwork stuff
                            String fullXml = reader.ReadToEnd();
                            int closePlistIndex = fullXml.IndexOf("</plist>") + 8;
                            fullXml = value + " " + fullXml.Remove(closePlistIndex);

                            // Load text as XML
                            XmlDocument document = new XmlDocument();
                            document.LoadXml(fullXml);

                            // Get all Keys (cast, directors, screenwriters, and producers)
                            XmlNodeList keys = document.SelectNodes("plist/dict/key");
                            foreach (XmlNode key in keys)
                            {
                                // cast, directors, screenwriters, or producers
                                String title = key.InnerText.Substring(0, 4).ToLower();

                                // every names inside
                                XmlNodeList persons = key.NextSibling.SelectNodes("dict/string");
                                List<String> names = new List<string>();
                                foreach (XmlNode person in persons)
                                {
                                    names.Add(person.InnerText);
                                }

                                metadata.SetValue(title, names);
                            }
                        }
                    }
                    else
                    {
                        metadata.SetValue(atomValue, value);
                    }
                }
            }

            reader.Close();
        }

        private void GenerateTextFile()
        {
            // Parse the input and generate strings to be used as arguments
            String inputFile = "\"" + filename + "\"";
            String outputFile = filename.Substring(0, filename.Length - 3) + "txt";

            // Specify process information
            ProcessStartInfo psi = new ProcessStartInfo(exePath, inputFile + " -t");
            psi.WindowStyle = ProcessWindowStyle.Normal;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = true;
            psi.RedirectStandardOutput = true;
			psi.CreateNoWindow = true;
            
            // Start the process
            Process p = System.Diagnostics.Process.Start(psi);

            // Output the result from console to file
            File.WriteAllText(outputFile, p.StandardOutput.ReadToEnd());
			
			p.Close();
        }

        private void GeneratePicture()
        {
            String arguments = "\"" + filename + "\"";
			String picExePath = exePath + @"Artwork";
			
			// Specify process information
            ProcessStartInfo psi = new ProcessStartInfo(picExePath, arguments + " -E");
            psi.WindowStyle = ProcessWindowStyle.Normal;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = true;
            psi.RedirectStandardOutput = true;
			psi.CreateNoWindow = true;
            
            // Start the process
            Process p = System.Diagnostics.Process.Start(psi);

            String consoleOutput = p.StandardOutput.ReadToEnd();
            int length = consoleOutput.Length;

            int extensionIndex = consoleOutput.IndexOf(".png");
            if (extensionIndex == -1)
                extensionIndex = consoleOutput.IndexOf(".jpg");
            if (extensionIndex != -1)
            {
                int leftLength = length - extensionIndex - 4;
                picPath = consoleOutput.Substring(27, length - 27 - leftLength);
            }
			
            p.Close();
        }
		
		public String GetArtworkPath()
        {
            return picPath;
        }
		
		private String ResolveEXEPath()
		{
			String result = Environment.CommandLine;
			
			result = result.Remove(result.IndexOf("VideoFlowTaggerMacGUI.exe"));
			result = result + @"AtomicParsley";
			
			return result;
		}
    }
}
